#include <iostream>
#include <queue>
#include <vector>
#include <cstdio>
#include <unistd.h>

#include "Thread.hpp"
#include "lockGurad.hpp"
#include "log.hpp"

const int defalut_num = 5;

template<class T>
class ThreadPool
{
//用于锁相关的函数
public:
    //获得互斥锁
    pthread_mutex_t* getLock()
    {
        return &_lock;
    }
    //是否为空
    bool isEmpty()
    {
        return _queue.empty();
    }
    //等待条件
    void waitCond()
    {
        pthread_cond_wait(&_cond,&_lock);
    }
    //获取任务
    T getTask()
    {
        T tmp = _queue.front();
        _queue.pop();
        return tmp;
    }

public:
    ThreadPool(int num = defalut_num):_num(num)
    {
        //初始化锁
        pthread_mutex_init(&_lock,nullptr);
        pthread_cond_init(&_cond,nullptr);
        for(int i = 1;i <= _num;i++)
        {
            //初始化线程
            _threads.push_back(new Thread(i,routinue,this));
        }
    }
    void run()
    {
        for(auto& iter:_threads)
        {
            iter->start();
            //std::cout << "启动成功" << std::endl;
            logMessage(NORMAL,"%s %s",iter->getName().c_str(),"启动成功");
        }
    }
    //只有主进程会进来，所以直接用定义的锁
    void push_Task(const T& task)
    {
        lockGurad lg(&_lock);
        _queue.push(task);
        //通知其他线程
        pthread_cond_signal(&_cond);
    }
    static void* routinue(void* args)
    {
        ThreadData* td =(ThreadData*)args;
        ThreadPool<T>* tp = (ThreadPool<T> *)td->_args;
        while(true)
        {
            //lock
            //判断是否空了（控制线程同步）
            //获取一个任务
            //unlock
            //处理任务

            T task;
            //在这个作用域起作用的锁
            {
                lockGurad lg(tp->getLock());
                if(tp->isEmpty()) tp->waitCond();
                //读取任务
                task = tp->getTask();
            }
            task(td->_name);   //括号重载、执行任务
            //std::cout << "我是一个线程：" << td->_name << std::endl;
            //sleep(1);
        }
    }
    // void joins()
    // {
    //     for(auto& iter:_threads)
    //     {
    //         iter->join();
    //     }
    // }
    ~ThreadPool()
    {
        for(auto& iter:_threads)
        {
            iter->join();
            delete iter;
        }
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
    }

private:
    std::vector<Thread*> _threads;
    int _num;
    std::queue<T> _queue;

    pthread_mutex_t _lock;
    pthread_cond_t _cond;
    //1:27
    //2:08
};